using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Windows.Forms;
using Newtonsoft.Json;

namespace ChinaTax.LeQi
{
    public class Request<T> where T: Response, new()
    {
        [JsonIgnore]
        public string ServiceCode = string.Empty;

        static Request()
        {
            ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) => true;
        }

        private void Log(string text)
        {
            if (!Directory.Exists(Path.Combine(Application.StartupPath, "Log\\")))
                Directory.CreateDirectory(Path.Combine(Application.StartupPath, "Log\\"));

            File.AppendAllText(Path.Combine(Application.StartupPath, "Log\\LeQi_" + DateTime.Now.ToString("yyyyMMdd") + ".log"), text + Environment.NewLine);
        }

        private bool HttpPost(string url, ref string data, ref string message)
        {

            if (LeQiConfig.IsDebug)
            {
                Log(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + " Call HttPost ...");
                Log(url);
                Log(data);
            }

            data = SM4.SM4Helper.EncryptECB(LeQiConfig.LeQiKey, data);

            Log(data);

            try
            {
                var dataBytes = Encoding.UTF8.GetBytes(data);

                var request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "POST";
                //request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = dataBytes.Length; //Encoding.UTF8.GetByteCount(data);
                request.KeepAlive = false;
                request.UserAgent = "ChinaTax.LeQi/1.0";
                request.Timeout = 60 * 5 * 1000;

                request.Headers.Add("fwbm", ServiceCode); //添加服务编码
                request.Headers.Add("jrdwptbh", LeQiConfig.LeQiId); //添加接入单位平台编号
                request.Headers.Add("sydwptbh", LeQiConfig.LeQiId); //添加使用单位平台编号
                request.Headers.Add("nlbm", "202007"); //添加能力编码
                request.Headers.Add("ylbm", "911001"); //添加用例编码
                request.Headers.Add("access_signature", ""); //添加访问签名
                request.Headers.Add("sxcsbz", ""); //添加沙箱测试标志

                var reqStream = request.GetRequestStream();
                reqStream.Write(dataBytes, 0, dataBytes.Length);
                reqStream.Close();

                var response = (HttpWebResponse)request.GetResponse();

                var respStream = response.GetResponseStream();
                var respStreamReader = new StreamReader(respStream, Encoding.UTF8);

                var retString = respStreamReader.ReadToEnd();

                respStreamReader.Close();
                respStream.Close();

                data = retString;

                if (LeQiConfig.IsDebug)
                    Log(data);

                return true;
            }
            catch (Exception e)
            {
                message = e.Message;
                return false;
            }
        }

        protected virtual string GetBody()
        {
            var body = JsonConvert.SerializeObject(this);

            return body;
        }

        protected virtual string Data()
        {
            //生成请求数据
            return string.Empty;
        }

        public T Execute()
        {
            var body = GetBody();
            var msg = string.Empty;

            var result = HttpPost(LeQiConfig.Url + ServiceCode, ref body, ref msg);

            if (!result)
                return new T() { ReturnCode = "99", ReturnMsg = msg };

            var innerHttpResp = JsonConvert.DeserializeObject<InternalHttpResponse>(body);

            if (innerHttpResp == null || string.IsNullOrEmpty(innerHttpResp.httpStatusCode))
                return new T() { ReturnCode = "99", ReturnMsg = "Http 结果解析失败！" };

            if (innerHttpResp.httpStatusCode != "200") //HttpStatusCode.OK
                return new T() { ReturnCode = innerHttpResp.httpStatusCode, ReturnMsg = innerHttpResp.body };

            var innerRespWrap = JsonConvert.DeserializeObject<InternalResponseWrap>(innerHttpResp.body);

            if (innerRespWrap == null || innerRespWrap.Response == null)
                return new T() { ReturnCode = "99", ReturnMsg = "请求解析失败！" };

            var innerResp = innerRespWrap.Response;

            if (innerResp.Error != null)
                return new T() { ReturnCode = innerResp.Error.Code, ReturnMsg = innerResp.Error.Message };

            if (!string.IsNullOrEmpty(innerResp.Data))
            {
                var data = SM4.SM4Helper.DecryptECB(LeQiConfig.LeQiKey, innerResp.Data);

                Log(data);

                var resp = JsonConvert.DeserializeObject<T>(data);

                if (resp is IParse parse)
                    parse.Parse(data);

                return resp;
            }

            return new T() { ReturnCode = "UNKNOW", ReturnMsg = "未知错误！" };
        }
    }
}
